package cn.yuemouren.array;


/**
 * @Author: Timi
 * @Description: 封装数组操作类
 * @Date: 2020/4/28 10:36
 * @Version: v1.0
 */
public class Array<T> {

    private final static int DEFAULT_CAPACITY = 20;//默认容量

    private T[] data;
    private int size;

    public Array() {
       this(DEFAULT_CAPACITY);
    }

    /**
     * 添加初始容量数组
     * @param capacity 初始容量
     */
    public Array(int capacity) {
        this.data = (T[]) new Object[capacity];
    }

    /**
     * 传入数组
     * @param array
     */
    public Array(T[] array){
        data = (T[])new Object[array.length];
        for (int i = 0; i < data.length; i++){
            data[i] = array[i];
        }
        size = data.length;
    }

    public void addLast(T value){
        add(size,value);
    }

    public void addFirst(T value){
        add(0,value);
    }

    /**
     * 根据索引，添加值
     * @param index 索引
     * @param value 值
     */
    public void add(int index,T value){
        if(index < 0 || index > size){
            throw new IllegalArgumentException("Array param is fail");
        }
        if(size == data.length){
            resize(getCapacity() * 2);
        }
        for (int i = size-1; i >= index ; i--){
            data[i+1] = data[i];
        }
        data[index] = value;
        size++;
    }

    public T removeFirst(){
        return remove(0);
    }

    public T removeLast(){
        return remove(size-1);
    }

    /**
     * 根据指定值删除
     * @param value
     */
    public void removeElement(T value){
        if(size == 0){
            throw new IllegalArgumentException("Array data is empty");
        }
        int index = find(value);
        if(index != -1){
            remove(index);
        }
    }

    /**
     * 删除指定索引上的值
     * @param index 索引
     * @return 返回删除掉的值
     */
    public T remove(int index){
        if(size == 0){
            throw new IllegalArgumentException("Array data is empty");
        }
        if(index < 0 || index >= size){
            throw new IllegalArgumentException("Array param is fail");
        }
        T res = data[index];
        for (int i = index;i < size;i++){
            data[i] = data[i+1];
        }
        size--;
        if(size < data.length / 2 && data.length / 2 != 0){
            resize(data.length / 2);
        }
        return res;
    }

    /**
     * 数组中是否包含指定值
     * @param value 值
     * @return
     */
    public boolean contains(T value){
        if(size == 0){
            throw new IllegalArgumentException("Array data is empty");
        }
        for (int i = 0; i < size; i++){
            if(data[i] == value){
                return true;
            }
        }
        return false;
    }

    /**
     * 根据值返回索引
     * @param value 值
     * @return 索引
     */
    public int find(T value){
        if(size == 0){
            throw new IllegalArgumentException("Array data is empty");
        }
        for (int i = 0; i < size; i++){
            if(data[i] == value){
                return i;
            }
        }
        return -1;
    }

    private void resize(int newCapacity){
        T[] newData = (T[]) new Object[newCapacity];
        for (int i=0; i < size;i++){
            newData[i] = data[i];
        }
        data = newData;
    }

    public T get(int index){
        if(size == 0){
            throw new IllegalArgumentException("Array data is empty");
        }
        if(index < 0 && index > size - 1){
            throw new IllegalArgumentException("Array data is empty");
        }
        return data[index];
    }

    public T set(int index,T t){
        if(size == 0){
            throw new IllegalArgumentException("Array data is empty");
        }
        if(index < 0 && index > size - 1){
            throw new IllegalArgumentException("Array data is empty");
        }
        T res = get(index);
        data[index] = t;
        return res;
    }

    public T getFirst(){
        return get(0);
    }

    public T getLast(){
        return get(size - 1);
    }

    /**
     * 获取实际存储数量
     * @return
     */
    public int getSize(){
        return size;
    }

    /**
     * 返回容量
     * @return
     */
    public int getCapacity(){
        return data.length;
    }

    public boolean isEmpty(){
        return size == 0 ? true : false;
    }

    public void swap(int i,int j){
        if(i < 0 || i >= getSize() || j < 0 || j >= getSize()){
            throw new IllegalArgumentException("params is error");
        }
        T t = data[i];
        data[i] = data[j];
        data[j] = t;
    }

    @Override
    public String toString(){
        StringBuilder sb = new StringBuilder();
        sb.append("Array: size = "+size);
        sb.append(",capacity = "+data.length+"\n");
        sb.append("[");
        for (int i = 0; i < size; i++){
            sb.append(data[i]+"");
            if(i < size-1){
                sb.append(",");
            }
        }
        sb.append("]");
        return sb.toString();
    }
}
